''''''

# Standard
import os
import sys
import optparse
import warnings
import ConfigParser
# Related
# Local
import moopy.errors


#: The version of the embedded Python in modo.
modos_pyver = (2, 6, 2)

def add_import_path(config, path):
    ''''''

    if '<' in path:
        # We are using < as a separator character for the paths.
        # If they try to use it, slap them.

        raise moopy.errors.SetupError(
            'The "<" character is reserved by Moopy and cannot be in '
            'any paths you attempt to add.')

    if config.has_option('moopy_config', 'paths'):
        current_paths = config.get('moopy_config', 'paths').split('<')
    else:
        current_paths = []

    # If the path already exists, raise an error.
    if current_paths.count(path):
        raise moopy.errors.SetupError(
            'You are attempting to add a path that already exists in the '
            'config\'s path.')

    # Append the path
    current_paths.append(path)

    # Re-add it to the config
    config.set('moopy_config', 'paths', '<'.join(current_paths))

    # Add our own "modified" variable to the config setup. I know, a bit
    # of a nono.
    config.modified = True

def add_python(config):
    ''''''

    # Check the python version, and compare it to modo's embedded version.
    # As of 401, this is Python 2.6.2.

    if sys.version_info[0] != modos_pyver[0]:
        raise moopy.errors.SetupError(
            'The Python version you are running this script from is not '
            'compatible with modo\'s embedded Python version. Please '
            'run this script from a Python version in the '
            '%s.%s.x series. ' % (modos_pyver[0], modos_pyver[1]))

    if sys.version_info[1] != modos_pyver[1]:
        warnings.warn(
            'Your Python version is not the same as modo\'s embedded '
            'Python version. As a result, some imported libraries may '
            'not operate properly.')

    config.set('moopy_config', 'python_path',
               os.path.join(sys.exec_prefix, 'Lib', 'site-packages'))

    # Add our own "modified" variable to the config setup. 
    config.modified = True

def handle_aguments():
    '''This will create an OptionParser instance, add options, and
    return the value/raise exceptions for this script file.
    '''

    parser = optparse.OptionParser()

    parser.add_option(
        '-a', '--add_import_path', dest='add_import_path',
        help='''Add a specified path to Python's sys.path,
        allowing for modules to be imported from that directory.'''
    )

    parser.add_option(
        '-l', '--list_paths', dest='list_paths',
        action='store_true', default=False,
        help='''List all of the paths defined in the moopy config.'''
    )

    parser.add_option(
        '-p', '--add_python', dest='add_python',
        action='store_true', default=False,
        help='''Attempt to find and add the system Python install if one
        can be found that matches modo. Alternatively, if one cannot be
        found, simply add the path by supplying Python's site_packages
        path to the "-a" option.'''
    )

    parser.add_option(
        '-r', '--remove_path', dest='remove_path',
        help='''Remove a path from the moopy config. Note that the path names
        must match exactly.'''
    )

    parser.add_option(
        '-R', '--remove_config', dest='remove_config',
        action='store_true', default=False,
        help='''Delete the entire moopy config. There is no going back with
        this option either, so be sure you want to do it.'''
    )

    return parser.parse_args()

def list_paths(config):
    '''List all the import paths found in the config.'''

    if config.has_option('moopy_config', 'paths'):
        for import_path in config.get('moopy_config', 'paths').split('<'):
            print 'Path: "%s"' % import_path
        print ''
    else:
        print 'No paths exist.'
        print ''

def remove_path(config, path):
    ''''''

    if not config.has_option('moopy_config', 'paths'):
        # If no paths even exist, we can't remove anything.
        raise moopy.errors.SetupError(
            'No paths exist in the config, so you cannot remove anything.')

    current_paths = config.get('moopy_config', 'paths')

    if not current_paths.count(path):
        # If the path doesn't exist in the config, we can't remove it.

        raise moopy.errors.SetupError(
            'The path you are attempting to remove from the config '
            'does not exist in the config, so you cannot remove it.')

    current_paths.remove(path)

    # Re-add it to the config
    config.set('moopy_config', 'paths', current_paths)

    # Add our own "modified" variable to the config setup.
    config.modified = True

if __name__ == '__main__':
    moopy_file_path = os.path.join(os.path.dirname(__file__), 'moopy.cfg')

    config = ConfigParser.RawConfigParser()
    config.read(moopy_file_path)

    # If the "moopy_config" section has not been defined, create it.
    if not config.has_section('moopy_config'):
        config.add_section('moopy_config')

    # Get the script arguments.
    (options, args) = handle_aguments()

    # Set modified to false.
    # Note that this is a bit hackey, but it's better than writing on every
    # function, and also better than writing on every script execution.
    config.modified = False

    if options.add_import_path is not None:
        add_import_path(config, options.add_import_path)

    if options.add_python:
        add_python(config)

    if options.remove_path is not None:
        remove_path(config, options.remove_path)

    if options.list_paths:
        list_paths(config)

    if options.remove_config:
        # Before we remove the config, check if the user just modified it.
        # If they did, lets raise an error to be nice.

        if config.modified:
            raise moopy.errors.SetupError(
                'The config has been modified in this execution. If you '
                'intend to delete the config, only supply the -R argument.')

        # No, they didn't modify it? Alright, kill the file.
        os.remove(moopy_file_path)

    if config.modified:
        # If our config was modified, write it to file.
        config.write(open(moopy_file_path, 'wb'))

